using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Text;
using Firestarter.DB.Schema.BO;
using FireStarterModeller.BO;
using FireStarterModeller.UI;
using FireStarterModeller.UI.CodeGeneration;
using FireStarterModeller.UI.DatabaseConnection;
using FireStarterModeller.UI.Dialogs;
using Habanero.Base;
using Habanero.BO;
using Habanero.DB;
using Habanero.Faces.Base;
using Habanero.Faces.Win;
using Habanero.BO.ClassDefinition;
using DockStyle = System.Windows.Forms.DockStyle;
using UIForm=Habanero.BO.ClassDefinition.UIForm;

namespace Firestarter.DB.Schema.UI
{
    public class ChooseDatabaseConnectionWizardStep : WizardStepWin
    {
        private readonly IControlFactory _controlFactory = GlobalUIRegistry.ControlFactory;

        private DatabaseConnectionGridAndEditorControl _databaseConnectionGridAndEditorControl;

        private ReverseEngineering _reverseEngineering;
        private SingleRelationship<DatabaseConnectionInfo> _databaseConnectionInfoRelationship;
        private IGroupBox _databaseConnectionGroupBox;

        public const string SelectConnectionMessage = "Please select a database connection.";

        public ChooseDatabaseConnectionWizardStep()
        {
            SetupDatabaseConnectionControl();

            LayoutControls();
        }

        private void LayoutControls()
        {
            IControlFactory factory = _controlFactory;
            BorderLayoutManager layoutManager = factory.CreateBorderLayoutManager(this);
            layoutManager.AddControl(_databaseConnectionGroupBox, BorderLayoutManager.Position.Centre);
        }

        private void SetupDatabaseConnectionControl()
        {
            _databaseConnectionGroupBox = _controlFactory.CreateGroupBox("Database Connection");
            _databaseConnectionGridAndEditorControl = SetupDatabaseConnectionInfoPanel();

            BorderLayoutManager groupBoxLayoutManager = _controlFactory.CreateBorderLayoutManager(_databaseConnectionGroupBox);
            groupBoxLayoutManager.AddControl(_databaseConnectionGridAndEditorControl, BorderLayoutManager.Position.Centre);

        }

        private DatabaseConnectionGridAndEditorControl SetupDatabaseConnectionInfoPanel()
        {
            var createConnectionGridAndEditor = new DatabaseConnectionGridAndEditorControl();
            var businessObjectCollection = Broker.GetBusinessObjectCollection<DatabaseConnectionInfo>("");
            createConnectionGridAndEditor.DatabaseConnectionInfos = businessObjectCollection;
            return createConnectionGridAndEditor;
        }

        public DatabaseConnectionInfo DatabaseConnectionInfo
        {
            get { return _databaseConnectionGridAndEditorControl.CurrentDatabaseConnectionInfo; }
            private set
            {
                var databaseConnectionInfos = _databaseConnectionGridAndEditorControl.DatabaseConnectionInfos;
                if (value != null && !databaseConnectionInfos.Contains(value)) databaseConnectionInfos.Add(value);
                _databaseConnectionGridAndEditorControl.CurrentDatabaseConnectionInfo = value;
            }
        }

        public ReverseEngineering ReverseEngineering
        {
            get { return _reverseEngineering; }
            set
            {
                if (_databaseConnectionInfoRelationship != null)
                {
                    _databaseConnectionInfoRelationship.Updated -= DatabaseConnectionInfoRelationship_Updated;
                }
                _reverseEngineering = value;
                if (_reverseEngineering != null)
                {
                    _databaseConnectionInfoRelationship = _reverseEngineering
                        .Relationships.GetSingle<DatabaseConnectionInfo>("DatabaseConnectionInfo");
                    _databaseConnectionInfoRelationship.Updated += DatabaseConnectionInfoRelationship_Updated;
                }
                UpdateDatabaseConnectionInfo();
            }
        }

        // ReSharper disable InconsistentNaming
        private void DatabaseConnectionInfoRelationship_Updated(object sender, BOEventArgs<DatabaseConnectionInfo> e)
        // ReSharper restore InconsistentNaming
        {
            UpdateDatabaseConnectionInfo();
        }

        private void UpdateDatabaseConnectionInfo()
        {
            this.DatabaseConnectionInfo = _reverseEngineering != null ? _reverseEngineering.DatabaseConnectionInfo : null;
        }

        #region Implementation of IWizardStep

        /// <summary>
        ///             Initialises the step. Run when the step is reached.
        /// </summary>
        public override void InitialiseStep()
        {

        }

        /// <summary>
        ///             Verifies whether this step can be passed.
        /// </summary>
        /// <param name="message">Error message should moving on be disallowed. This message will be displayed to the user by the WizardControl.</param>
        public override bool CanMoveOn(out string message)
        {
            return IsDatabaseConnectionValid(out message);
        }

        private bool IsDatabaseConnectionValid(out string message)
        {
            if (DatabaseConnectionInfo == null)
            {
                message = SelectConnectionMessage;
                return false;
            }
            return DatabaseConnectionInfo.IsDatabaseConnectionValid(out message);
        }

        /// <summary>
        ///             Verifies whether the user can move back from this step.
        /// </summary>
        public override bool CanMoveBack()
        {
            throw new System.NotImplementedException(); //TODO Mark 21 Jan 2009: Implement this
        }

        /// <summary>
        ///             Provides an interface for the developer to implement functionality to cancel any edits made as part of this
        ///             wizard step. The default wizard controller functionality is to call all wizard steps cancelStep methods when
        ///             its Cancel method is called.
        /// </summary>
        public override void CancelStep()
        {
            if (_reverseEngineering == null) return;
            if (_reverseEngineering.DatabaseConnectionInfo == null) return;
            _reverseEngineering.DatabaseConnectionInfo.CancelEdits();
        }
        /// <summary>
        ///             The text that you want displayed at the top of the wizard control when this step is active.
        /// </summary>
        public override string HeaderText
        {
            get { return "Select a valid database connection."; }
        }

        public DatabaseConnectionGridAndEditorControl DatabaseConnectionInfoControl
        {
            get { return _databaseConnectionGridAndEditorControl; }
        }

        #endregion
    }
}


